home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / AEObject-Edition1.0.2 Sample / Files.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-09  |  31.6 KB  |  787 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. *
  3. *  Apple Developer Technical Support
  4. *
  5. *  I/O handling routines
  6. *
  7. *  Program:    AEObject-Edition Sample
  8. *  File:       Files.c -   C Source
  9. *
  10. *  by:         C.K. Haun <TR>
  11. *
  12. *  Copyright © 1990-1992 Apple Computer, Inc.
  13. *  All rights reserved.
  14. *
  15. *------------------------------------------------------------------------------
  16. * This file handles saving and loadingg the documents created by this sample.
  17. * All the standard data load/save is taken care of in this file, while the 
  18. * Edition Manager specific routines for handling sections are in their own files  
  19. * (Publish.c or Subscribe.c) and are called from here.
  20. *----------------------------------------------------------------------------*/
  21.  
  22. /* File handling here */
  23. #define __FILES__
  24.  
  25. #pragma segment Files
  26.  
  27. #include "Sampdefines.h"
  28. static OSErr KillOldPrefs(void);
  29. /*  SaveMe saves the passes window data, and all the associated sections.
  30. *       It does NOT perform a 'safe' save, it kills the old data and recreates it.
  31. *       Future versions of this sample will do a 'safe' save.  Yeah, right, I wouldn't
  32. *        beleive me on THAT one.
  33. */
  34. /* windowCHandle is locked on entry to this  */
  35. void SaveMe(windowCHandle theWind, WindowPtr theWindPtr)
  36. {
  37.     Boolean myWasChanged;    /* for Alias Manager calls */
  38.     register qq;            /* counter */
  39.     StandardFileReply saveReply;    /* new System 7 standard file record */
  40.     short saveRefNum;
  41.     FSSpec saveFileSpec;
  42.     OSErr myErr;
  43.     Str255 wName;
  44.     Str63 savePrompt;
  45.     Handle nameStr;
  46.     long toWrite;    /* generic long */
  47.     
  48.     /* we need the window title for a prompt and also to change the name */
  49.     /* in the Window menu */
  50.     GetWTitle(theWindPtr, wName);
  51.     /* if the filealias handle is 0 size, then this file has not been saved yet, so we  */
  52.     /* need to call Standard File.  I'm using the new StandardGetFile call, this */
  53.     /* call is better in (at least) two ways.  First, you no longer pass a Point as */
  54.     /* a parameter, instead, the dialog is centered on the main screen for you.  Secondly, */
  55.     /* StandardGetFile returns a FSSpec record in the reply record.  This means that you */
  56.     /* can use the new FSp type calls, as well as using the FSSpec to generate an Alias */
  57.     /* easily. */
  58.     /* By the Way... if this is a 'Save As...' I have nulled out this handle so it */
  59.     /* looks like it's never been saved, look in Menus.c */    
  60.     if (GetHandleSize((Handle)(*theWind)->fileAliasHandle) == 0) {
  61.         /* get our prompt string */
  62.         GetIndString(savePrompt, kGeneralStrings, kSavePromptString);
  63.         /* display the new dialog */
  64.         StandardPutFile(savePrompt, wName, &saveReply);
  65.         if (!saveReply.sfGood)    /* did the user cancel? */
  66.             return;
  67.         /* get the returned file spec */    
  68.         saveFileSpec = saveReply.sfFile;
  69.         /* if they are replacing, destroy the old file now (aaaggggg) */
  70.         if (saveReply.sfReplacing)
  71.             FSpDelete(&saveFileSpec);
  72.         /* change the name of the window to this filename */
  73.         SetWTitle(theWindPtr, saveFileSpec.name);
  74.         AddToWindowMenu(theWindPtr,wName); /* remove the old name and replace it with this */
  75.     } else {
  76.         /* Resolve the old alias that was kept with the window  */
  77.         /* in this case I don't care if the alias needed to be updated or not, this ain't */
  78.         /* a real time critical routine */
  79.         myErr = ResolveAlias(nil, ((*theWind)->fileAliasHandle), &saveFileSpec, &myWasChanged);
  80.         if (myErr) {
  81.             ShowMe("\pResolving Alias ", myErr, __LINE__);
  82.             return;
  83.         }
  84.         /* kill current file, ignoring errors */
  85.         FSpDelete(&saveFileSpec);
  86.     }
  87.     SpinCursor();
  88.     /* create the new file */
  89.     myErr = FSpCreate(&saveFileSpec, kMySignature, kMyDocumentFileType, 1);
  90.     if (myErr) {
  91.         ShowMe("\pCreating file ", myErr, __LINE__);
  92.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  93.         return;
  94.     }
  95.     
  96.     /* replace the nil handle with the alias record please, in our window data struct */
  97.     DisposHandle((Handle)(*theWind)->fileAliasHandle);
  98.     if (myErr = NewAlias(nil, &saveFileSpec, &((*theWind)->fileAliasHandle))) {
  99.         ShowMe("\pDuring New Alias ", myErr, __LINE__);
  100.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  101.         return;
  102.     }
  103.     /* First save the drawing commands that make up this window */
  104.     
  105.     myErr = FSpOpenDF(&saveFileSpec, fsRdWrPerm, &saveRefNum);
  106.     if (myErr) {
  107.         ShowMe("\pOpening file ", myErr, __LINE__);
  108.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  109.         return;
  110.     }
  111.     /* save off lines, rects, ovals.  If there is a selection currently, it's lost */
  112.     /* shapes */
  113.     toWrite = sizeof(short);
  114.     SpinCursor();
  115.     myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&(*theWind)->numShapes);
  116.     if (myErr) {
  117.         ShowMe("\pWriting file ", myErr, __LINE__);
  118.     }
  119.     if ((*theWind)->numShapes) {
  120.         ShapesHandle theShape = (*theWind)->theShapes;
  121.         do {
  122.             toWrite = sizeof(Shapes);
  123.             HLock((Handle)theShape);
  124.             myErr = FSWrite(saveRefNum, &toWrite, (Ptr)*theShape);
  125.             HUnlock((Handle)theShape);
  126.             if (myErr) {
  127.                 ShowMe("\pWriting shapes ", myErr, __LINE__);
  128.                 break;
  129.             }
  130.             theShape = (*theShape)->nextShape;
  131.         }
  132.                 while (theShape);
  133.     }
  134.     
  135.     /* and pictures, I'm putting them in the data fork just because, OK? */
  136.     /* Actually, I'm doing it to prevent any conflict with resource for  */
  137.     /* subscribers cached pictures.  I could check for unique IDs and all that, but sometimes */
  138.     /* simplicity works well.... */
  139.       if(!myErr){  
  140.     toWrite = sizeof(short);
  141.     SpinCursor();
  142.     myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&(*theWind)->numPicts);
  143.     if(!myErr){
  144.     if ((*theWind)->numPicts != 0) {
  145.         Handle * thePict;
  146.         Handle *thePictRect;
  147.         /* get my picture handles and my picture placement rectangles */
  148.         HLock((Handle)(*theWind)->pictHandle);
  149.         HLock((Handle)(*theWind)->pictRects);
  150.         thePict = (Handle *)*(*theWind)->pictHandle;
  151.         thePictRect = (Handle *)*(*theWind)->pictRects;
  152.         for (qq = 0; qq < (*theWind)->numPicts; qq++) {
  153.             short writeSize;
  154.             toWrite = sizeof(short);
  155.             /* write everything about the picture out */
  156.             writeSize = GetHandleSize((Handle)*thePict);
  157.             myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&writeSize);
  158.             toWrite = writeSize;
  159.             HLock((Handle)*thePict);
  160.             if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)(*(*thePict)));
  161.             HUnlock((Handle)*thePict);
  162.             /* and the rect */
  163.             toWrite = sizeof(Rect);
  164.             HLock((Handle)*thePictRect);
  165.             if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)(*(*thePictRect)));
  166.             HUnlock((Handle)*thePictRect);
  167.             thePictRect += 1;
  168.             thePict += 1;
  169.             SpinCursor();
  170.         }
  171.         HUnlock((Handle)(*theWind)->pictHandle);
  172.         HUnlock((Handle)(*theWind)->pictRects);
  173.     }
  174.     }
  175.     }
  176.     toWrite = sizeof(short);
  177.     /* if there's any text in a TE record, write that out also */
  178.     if(!myErr){
  179.     if ((*theWind)->boxHandle != nil) {
  180.         CharsHandle theText;
  181.         short textLen;
  182.         /* save the text and the rectangle */
  183.         theText = TEGetText((*theWind)->boxHandle);
  184.         HLock((Handle)theText);
  185.         textLen = GetHandleSize((Handle)theText);
  186.         /* have to write it out the length of the text now */
  187.         toWrite = sizeof(short);
  188.         SpinCursor();
  189.         myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&textLen);
  190.         /* and the text itself */
  191.         toWrite = textLen;
  192.         if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)*theText);
  193.         /* and save out the rectangle */
  194.         toWrite = sizeof(Rect);
  195.         if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&(*theWind)->textBox);
  196.     } else {
  197.         short nothing = 0;
  198.         myErr = FSWrite(saveRefNum, &toWrite, (Ptr)¬hing);       /* a pointer to nothing.  Leads to the 'No Exit' sign in Sartè */
  199.     }
  200.     }
  201.     if(myErr)
  202.         ShowMe("\p Error writing data fork",myErr,__LINE__);
  203.     if(saveRefNum)FSClose(saveRefNum);
  204.     /* this takes care of the data fork of the file.  Now we need to save 
  205.     *   publisher and subcriber data in the resource fork */
  206.     HCreateResFile(saveFileSpec.vRefNum, saveFileSpec.parID, saveFileSpec.name);
  207.     if (myErr = ResError()) {
  208.         ShowMe("\pCreating Rez fork", myErr, __LINE__);
  209.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  210.         return;
  211.     }
  212.     saveRefNum = HOpenResFile(saveFileSpec.vRefNum, saveFileSpec.parID, saveFileSpec.name, fsRdWrPerm);
  213.     if (myErr = ResError()) {
  214.         ShowMe("\pHOpening resource fork ", myErr, __LINE__);
  215.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  216.         return;
  217.     }
  218.     /* add our 'name' string to this file (see 'The Finder Interface' chapter of IM VI) */
  219.     nameStr = GetResource('STR ', kMyAppNameString);
  220.     DetachResource(nameStr);
  221.     UseResFile(saveRefNum);
  222.     AddResource(nameStr, 'STR ', -16396, ""); /* no constant for this number, should be */
  223.     /* HandleSectionSave saves off the 'sect' and 'alis' resources for all our */
  224.     /* publishers and subscribers */
  225.     HandleSectionSave(theWind, true, false, &saveFileSpec);
  226.     CloseResFile(saveRefNum);
  227.     FlushVol("", saveFileSpec.vRefNum);
  228.     (*theWind)->windowDirty = false;
  229.     SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  230. }
  231.  
  232. /* end SaveMe */
  233.  
  234. /* OpenFile reads in our drawing commands, and all the publisher and */
  235. /* subscriber data, and registers all our sections */
  236. WindowPtr OpenFile(FSSpec *inSpec)
  237. {
  238.     long numSections;
  239.     long counter = 0;
  240.     OSErr myErr;
  241.     WindowPtr newWindow;
  242.     windowCHandle newWinControl;
  243.     Handle textFromFile;
  244.     FSSpec readFileSpec;
  245.     short readRefNum;
  246.     StandardFileReply openReply;
  247.     SFTypeList myList =  {
  248.         kMyDocumentFileType
  249.     };
  250.     
  251.     if (inSpec) {    /* if it was called by an ODOC AppleEvent then our AppleEvent handler */
  252.         /* will pass the FSSpec that the AE contained */
  253.         readFileSpec = openReply.sfFile = *inSpec;
  254.     } else {
  255.     /* if the spec is nil, that means it's a menu selection, so we use StandardFile */
  256.         StandardGetFile((FileFilterProcPtr)0, 1, myList, &openReply);
  257.         if (!openReply.sfGood)
  258.             return(nil);                                    /* scat if they canceled */
  259.         readFileSpec = openReply.sfFile;
  260.     }
  261.     if ((openReply.sfType != kMyDocumentFileType) && (inSpec == nil)) {
  262.         ShowMe("\pfilter not working", 0, __LINE__);
  263.         return(nil);
  264.     }
  265.     if(CheckExisting(&readFileSpec)){
  266.         /* if it already eisists, bring it up */
  267.         WindowToFront(nil,readFileSpec.name);
  268.         return(FrontWindow());
  269.         }
  270.         SpinCursor();
  271.     newWindow = AddNewWindow(false);                        /* ask for a new window */
  272.     if (newWindow == nil) {
  273.         InitCursor();
  274.         return(nil);
  275.     }                                                       /* bail if it failed */
  276.     newWinControl = (windowCHandle)GetWRefCon(newWindow);
  277.     HLock((Handle)newWinControl);
  278.     /* window opened, set title to file name, and create an alias to store in the */
  279.     /* struct. */
  280.     SetWTitle(newWindow, readFileSpec.name);
  281.     DisposHandle((Handle)(*newWinControl)->fileAliasHandle);        /* kill the null handle */
  282.     if (myErr = NewAlias(nil, &readFileSpec, &((*newWinControl)->fileAliasHandle))) {
  283.         ShowMe("\pDuring New Alias ", myErr, __LINE__);
  284.         return(nil);
  285.     }
  286.     /* now open the data fork of the file and read in our drawing commands */
  287.     if (myErr = FSpOpenDF(&openReply.sfFile, fsRdPerm, &readRefNum)) {
  288.         ShowMe("\pOpening file ", myErr, __LINE__);
  289.         return(nil);
  290.     }
  291.     SpinCursor();
  292.     ReadDocData(newWinControl, readRefNum);
  293.     SpinCursor();
  294.     readRefNum = HOpenResFile(readFileSpec.vRefNum, readFileSpec.parID, readFileSpec.name, fsRdWrPerm);
  295.     UseResFile(readRefNum);
  296.     /* now load in the sections and aliases */
  297.     /* Load each section, and store it in the appropriate area (pub or sub) */
  298.     /* Then register the sections.  */
  299.     /* ••• NOTE: As soon as you register a section, the Edition Manager may generate an */
  300.     /* event for that section.  All the subscribers may get a Section Read event, for */
  301.     /* example, and some of the publishers will probably get a section write.  */
  302.     /*  So, don't assume anything.  Don't write sections or read sections yourself, wait for */
  303.     /* the Edition Manager to generate the right events, this will insure that you are always */
  304.     /* current and NOT fighting with the EM */
  305.     /* how many sections are there? */
  306.     numSections = Count1Resources(rSectionType);
  307.     /* loop through them all */
  308.     if (numSections) {
  309.         for (counter = 0; counter < numSections; counter++) {
  310.             SectionHandle inSection;
  311.             AliasHandle inAlias;
  312.             Handle auxDataIn;
  313.             short inID;
  314.             ResType tempRT;
  315.             Str255 tempRName;
  316.             Boolean aliasUpdated;
  317.             SpinCursor();
  318.             inSection = (SectionHandle)Get1IndResource(rSectionType, counter + 1);
  319.             /* this GetResInfo call is here to give us the ResID of the section.  Since the alias */
  320.             /* for this section was stored with the same ID, we can get it easily. */
  321.             GetResInfo((Handle)inSection, &inID, &tempRT, &tempRName);
  322.             inAlias = (AliasHandle)Get1Resource(rAliasType, inID);
  323.             myErr = ResError();
  324.             if ((myErr != 0) || (inAlias == nil))
  325.                 ShowMe("\palias error", myErr, __LINE__);
  326.             DetachResource((Handle)inSection);
  327.             DetachResource((Handle)inAlias);
  328.             /* depending on our type depends on what else we bring in */
  329.             /* text data or picture stuff */
  330.             switch ((*inSection)->refCon & 0xf) {
  331.                 case kPictType:
  332.                     auxDataIn = Get1Resource('RECT', inID);
  333.                     DetachResource(auxDataIn);
  334.                     break;
  335.                 case kTextType:
  336.                     /* I do need */
  337.                     /* to get my textSection record back so I have my start-end offsets */
  338.                     auxDataIn = Get1Resource(rMyTextRecordType, inID);
  339.                     DetachResource(auxDataIn);
  340.                     break;
  341.                     
  342.             }
  343.             /* Put the alias in the section, since the old handle stored there means nothing now */
  344.             
  345.             (*inSection)->alias = inAlias;
  346.             /* now we have to determine if this was a pub or sub, since we have to load the */
  347.             /* publish rectangle resource if it was a publisher */
  348.             /* Now tell the Edition Manager that this section is back on line and ready to */
  349.             /* receive events */
  350.             if (myErr = RegisterSection(&readFileSpec, inSection, &aliasUpdated)) {
  351.                 ShowMe("\pRegistering Section ", myErr, __LINE__);
  352.                 /*    return; */
  353.                 inSection = nil;
  354.             }
  355.             if (inSection) {
  356.                 
  357.                 if ((*inSection)->kind == stPublisher) {
  358.                     
  359.                     /* get the rectangle */
  360.                     switch ((*inSection)->refCon & 0xf) {
  361.                         case kPictType:
  362.                             HLock(auxDataIn);
  363.                             StorePublisher(newWinControl, inSection, (Rect *)*auxDataIn, nil, 'PICT');  /* in Publish.c */
  364.                             DisposHandle(auxDataIn);
  365.                             /* mark all incoming sections as having been saved once, so we don't */
  366.                             /* delete them accidentalllly when this window closes */
  367.                             (*inSection)->refCon |= kSavedOnce;
  368.                             
  369.                             break;
  370.                         case kTextType:
  371.                             /* need to get the text contained in this thing */
  372.                             textFromFile = Get1Resource(rMyTextBlock, inID);
  373.                             DetachResource(textFromFile);
  374.                             (*(mySectionDataHandle)auxDataIn)->additionalData = textFromFile;
  375.                             /* associate the section with the text section */
  376.                             (*(mySectionDataHandle)auxDataIn)->theSection = inSection;
  377.                             /* and store it away */
  378.                             
  379.                             StorePublisher(newWinControl, inSection, nil, (mySectionDataHandle)auxDataIn, 'TEXT');
  380.                             /* mark all incoming sections as having been saved once, so we don't */
  381.                             /* delete them accidentalllly when this window closes */
  382.                             (*inSection)->refCon |= kSavedOnce;
  383.                             break;
  384.                             
  385.                     }
  386.                 } else {
  387.                     Handle picIn;
  388.                     switch ((*inSection)->refCon & 0xf) {
  389.                         case kPictType:
  390.                             picIn = (Handle)GetPicture(inID);
  391.                             DetachResource((Handle)picIn);
  392.                             if (ResError())
  393.                                 ShowMe("\ppicture get", 0, __LINE__);
  394.                             /* need to get the picture here */
  395.                             StoreSubscriber(newWinControl, inSection, auxDataIn, picIn);        /* in Subscribe.c */
  396.                             break;
  397.                         case kTextType:
  398.                             /* need to get the text contained in this thing */
  399.                             textFromFile = Get1Resource(rMyTextBlock, inID);
  400.                             DetachResource(textFromFile);
  401.                             (*(mySectionDataHandle)auxDataIn)->additionalData = textFromFile;
  402.                             /* associate the section with the text section */
  403.                             (*(mySectionDataHandle)auxDataIn)->theSection = inSection;
  404.                             (*(mySectionDataHandle)auxDataIn)->nextSection = nil;
  405.                             /* and store it away */
  406.                             /* I'll be using the auxDataIn field for the mySectionDataHandle */
  407.                             StoreSubscriber(newWinControl, inSection, auxDataIn, nil);      /* in Subscribe.c */
  408.                             
  409.                             break;
  410.                     }
  411.                 }
  412.             }
  413.         }
  414.     }
  415.     CloseResFile(readRefNum);
  416.     (*newWinControl)->windowDirty = false;                  /* can't be dirty if I just opend it */
  417.     HUnlock((Handle)newWinControl);
  418.     ShowWindow(newWindow);
  419.     AddToWindowMenu(newWindow, nil);
  420.     ChangePlane(newWindow);
  421.     InitCursor();
  422.     return(newWindow);
  423. }
  424.  
  425. /* Reads the actual document data out of the file.  This is not in the OpenFile function */
  426. /* for secret reasons that will become apparent in a future release of this sample..... */
  427. /* the window control structure in this window ptr is locked on entry */
  428. /* I'm passing the window instaed of the window control handle because I may */
  429. /* have to create a text edit record */
  430. void ReadDocData(windowCHandle newWinControl, short readRefNum)
  431. {
  432.     long toRead;
  433.     register qq;
  434.     short aShort;
  435.     OSErr myErr;
  436.     short shapeCounter;
  437.     GetEOF(readRefNum, &toRead);
  438.     if (toRead) {                                           /* Make sure that there is some data to read */
  439.         /* lines */
  440.         toRead = sizeof(short);
  441.         FSRead(readRefNum, &toRead, (Ptr)&shapeCounter);
  442.         if (shapeCounter) {
  443.             ShapesHandle tempSH;
  444.             
  445.             for (qq = 0; qq < shapeCounter; qq++) {
  446.                 tempSH = NewShape(newWinControl);           /* number of shapes is getting incremented in this call */
  447.                 HLock((Handle)tempSH);
  448.                 toRead = sizeof(Shapes);
  449.                 myErr = FSRead(readRefNum, &toRead, (Ptr)*tempSH);
  450.                 if (myErr)
  451.                     ShowMe("\pReading shape", myErr, __LINE__);
  452.                 /* re-nul the nextShape field */
  453.                 (*tempSH)->nextShape = nil;
  454.                 HUnlock((Handle)tempSH);
  455.             }
  456.         }
  457.         toRead = sizeof(short);
  458.         FSRead(readRefNum, &toRead, (Ptr)&(*newWinControl)->numPicts);
  459.         if ((*newWinControl)->numPicts != 0) {
  460.             Handle * tempPictHand;
  461.             Handle *tempPictRects;
  462.             HUnlock((*newWinControl)->pictHandle);
  463.             HUnlock((*newWinControl)->pictRects);
  464.             MySetHandleSize((*newWinControl)->pictHandle, (sizeof(Handle) * ((*newWinControl)->numPicts)));
  465.             MySetHandleSize((*newWinControl)->pictRects, (sizeof(Handle) * ((*newWinControl)->numPicts)));
  466.             HLock((*newWinControl)->pictHandle);
  467.             HLock((*newWinControl)->pictRects);
  468.             tempPictRects = (Handle *)*((*newWinControl)->pictRects);
  469.             tempPictHand = (Handle *)*((*newWinControl)->pictHandle);
  470.             /* read in picts please */
  471.             for (qq = 0; qq < (*newWinControl)->numPicts; qq++) {
  472.                 short sizeIn;
  473.                 /* read size of pict, pict, and pict rect for each */
  474.                 toRead = sizeof(short);
  475.                 FSRead(readRefNum, &toRead, (Ptr)&sizeIn);
  476.                 *tempPictHand = NewHandle(sizeIn);
  477.                 HLock(*tempPictHand);
  478.                 toRead = sizeIn;
  479.                 FSRead(readRefNum, &toRead, (Ptr)(*(*tempPictHand)));
  480.                 HUnlock(*tempPictHand);
  481.                 *tempPictRects = NewHandle(sizeof(Rect));
  482.                 
  483.                 HLock(*tempPictRects);
  484.                 toRead = sizeof(Rect);
  485.                 FSRead(readRefNum, &toRead, (Ptr)(*(*tempPictRects)));
  486.                 HUnlock(*tempPictRects);
  487.                 tempPictRects += 1;
  488.                 tempPictHand += 1;
  489.             }
  490.             HUnlock((*newWinControl)->pictHandle);
  491.             HUnlock((*newWinControl)->pictRects);
  492.             
  493.         }
  494.         /* get any text */
  495.         toRead = sizeof(short);
  496.         FSRead(readRefNum, &toRead, (Ptr)&aShort);
  497.         if (aShort) {                                       /* if this has value (numerically, not ethically) then we need to make a TERecord */
  498.             CharsHandle theText;
  499.             Rect innerRect;
  500.             theText = (CharsHandle)NewHandle(aShort);
  501.             HLock((Handle)theText);
  502.             toRead = aShort;
  503.             FSRead(readRefNum, &toRead, (Ptr)*theText);
  504.             /* read in the rect */
  505.             toRead = sizeof(Rect);
  506.             FSRead(readRefNum, &toRead, (Ptr)&(*newWinControl)->textBox);
  507.             /* and create the TEControl */
  508.             innerRect = (*newWinControl)->textBox;
  509.             InsetRect(&innerRect, 3, 3);
  510.             (*newWinControl)->boxHandle = TENew(&innerRect, &(*newWinControl)->textBox);
  511.             TESetText((Ptr)*theText, aShort, (*newWinControl)->boxHandle);
  512.             DisposHandle((Handle)theText);
  513.         }
  514.     }
  515.     FSClose(readRefNum);
  516. }
  517.  
  518. /* LoadPrefs gets my preferences record out of the prefs file */
  519. void LoadPrefs(void)
  520. {
  521.     Handle prefs;
  522.     short prefFileID = OpenPrefsFile();
  523.     if (prefFileID) {
  524.         UseResFile(prefFileID);
  525.         /* load my private prefs resource */
  526.         prefs = Get1Resource(kMyPrefsResType, 128);
  527.         
  528.         if (prefs) {
  529.         /* it exsists */
  530.         
  531.             HLock(prefs);
  532.             BlockMove((Ptr)*prefs, (Ptr)&gPreferences, sizeof(prefStruct));
  533.               /* first check our version please */
  534.             if(gPreferences.version != kCurrentPrefsVersion){
  535.             ReleaseResource(prefs);
  536.             CloseResFile(prefFileID);            
  537.             if(noErr == KillOldPrefs())
  538.                 LoadPrefs();    /* a little recursion in the morning */
  539.             else
  540.                 return;
  541.             }
  542.             /* parse through and see if we need to xfer object definitions */
  543.             if(gPreferences.saveWindDef){
  544.             HLock((Handle)gWindObjSpecHandle);
  545.             BlockMove((Ptr)&gPreferences.savedWOD,(Ptr)*gWindObjSpecHandle,sizeof(WindowObjectDef));
  546.             HUnlock((Handle)gWindObjSpecHandle);
  547.             }
  548.             if(gPreferences.saveTextDef){
  549.             HLock((Handle)gTextObjSpecHandle);
  550.             BlockMove((Ptr)&gPreferences.savedTOD,(Ptr)*gTextObjSpecHandle,sizeof(TextObjectDef));
  551.             HUnlock((Handle)gTextObjSpecHandle);
  552.             }
  553.             if(gPreferences.saveShapeDef){
  554.             HLock((Handle)gShapeObjSpecHandle);
  555.             BlockMove((Ptr)&gPreferences.savedSOD,(Ptr)*gShapeObjSpecHandle,sizeof(ShapeObjectDef));
  556.             HUnlock((Handle)gShapeObjSpecHandle);
  557.             }
  558.             if(gPreferences.saveInteract){
  559.             gLocalInteraction = gPreferences.localInteraction;
  560.             gAESendInteraction= gPreferences.sendInteraction;
  561.             gAESwitchLayer= gPreferences.layerSwitch;
  562.             }
  563.             if(gPreferences.saveTarget)gAddressMode=gPreferences.targetMode;
  564.             if(gPreferences.saveReply)gReplyMode = gPreferences.replyMode;
  565.  
  566.             HUnlock(prefs);
  567.             ReleaseResource(prefs);
  568.         } else {
  569.         /* some default prefs if the resource is missing */
  570.         gPreferences.bringAEUp=true;
  571.          gPreferences.verboseAE=true;
  572.  
  573.         }
  574.         CloseResFile(prefFileID);
  575.     }
  576. }
  577.  
  578. /* SavePrefs saves my preferences, and creates the prefs resource if none exisiststsists */
  579. void SavePrefs(void)
  580. {
  581.     Handle prefs;
  582.     short prefFileID;
  583.     /* if no change, don't bother */
  584.     if(!gPreferences.prefsChanged)return;
  585.     prefFileID = OpenPrefsFile();
  586.     /* did the file open ???  */
  587.     if (prefFileID) {
  588.         /* yeah, get our resource */
  589.         prefs = Get1Resource(kMyPrefsResType, 128);
  590.         if (prefs) {
  591.         /* it exixsts.  */
  592.             HLock(prefs);
  593.            gPreferences.version = kCurrentPrefsVersion;
  594.            gPreferences.localInteraction=gLocalInteraction;
  595.              gPreferences.sendInteraction=gAESendInteraction;
  596.              gPreferences.layerSwitch=gAESwitchLayer;
  597.             
  598.             gPreferences.targetMode=gAddressMode;
  599.               gPreferences.replyMode=gReplyMode;
  600.  
  601.             /* move our object data into this thing here  */
  602.             HLock((Handle)gWindObjSpecHandle);
  603.             BlockMove((Ptr)*gWindObjSpecHandle,(Ptr)&gPreferences.savedWOD,sizeof(WindowObjectDef));
  604.             HLock((Handle)gTextObjSpecHandle);
  605.             BlockMove((Ptr)*gTextObjSpecHandle,(Ptr)&gPreferences.savedTOD,sizeof(TextObjectDef));
  606.             HLock((Handle)gShapeObjSpecHandle);
  607.             BlockMove((Ptr)*gShapeObjSpecHandle,(Ptr)&gPreferences.savedSOD,sizeof(ShapeObjectDef));
  608.             BlockMove((Ptr)&gPreferences, (Ptr)*prefs, sizeof(prefStruct));
  609.             HUnlock(prefs);
  610.             ChangedResource(prefs);
  611.         } else {
  612.         /* could not load the prefs resource, must not be there.  Create a new one */
  613.             prefs = NewHandle(sizeof(prefStruct));
  614.             HLock(prefs);
  615.             HLock((Handle)gWindObjSpecHandle);
  616.             
  617.             BlockMove((Ptr)*gWindObjSpecHandle,(Ptr)&gPreferences.savedWOD,sizeof(WindowObjectDef));
  618.             HLock((Handle)gTextObjSpecHandle);
  619.             BlockMove((Ptr)*gTextObjSpecHandle,(Ptr)&gPreferences.savedTOD,sizeof(TextObjectDef));
  620.             HLock((Handle)gShapeObjSpecHandle);
  621.             BlockMove((Ptr)*gShapeObjSpecHandle,(Ptr)&gPreferences.savedSOD,sizeof(ShapeObjectDef));
  622.            gPreferences.version = kCurrentPrefsVersion;
  623.             BlockMove((Ptr)&gPreferences, (Ptr)*prefs, sizeof(prefStruct));
  624.             AddResource(prefs, kMyPrefsResType, 128, "");
  625.             ChangedResource(prefs);
  626.         }
  627.         UpdateResFile(prefFileID);
  628.         CloseResFile(prefFileID);
  629.     }
  630. }
  631.  
  632. /* OpenPrefsFile opens, or creates and opens, my preferences file and returns   */
  633. /* the file reference number for it */
  634. short OpenPrefsFile(void)
  635. {
  636.     Handle prefsNameStr;
  637.     FSSpec prefsSpec;
  638.     short foundVREF;
  639.     short prefsID;
  640.     OSErr error;
  641.     long foundDIR;
  642.     /* Use FindFolder to get the dir and volume IDs for the preferences folder */
  643.     /* on the current system disko */
  644.     FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &foundVREF, &foundDIR);
  645.     /* get the name of my prefs file (resource, so it can be localized */
  646.     prefsNameStr = GetResource('STR ', kPrefsFileString);
  647.     HLock(prefsNameStr);
  648.     FSMakeFSSpec(foundVREF, foundDIR, (Str255)*prefsNameStr, &prefsSpec);
  649.     prefsID = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  650.     /* •••• Note: FSpOpenResFile returnd the file system error in ResError!  */
  651.     /* read the Resource Manager chapter of IM VI for more details */
  652.     error = ResError();
  653.     if (prefsID == -1) {
  654.         /* this means the prefs file couldn't be opened (IM VI chapter 13).  find out why */
  655.         prefsID = 0;                                        /* so later testing works better */
  656.         error = ResError();
  657.         if (error == fnfErr) {
  658.             /* create the file, then reopen it */
  659.             FSpCreateResFile(&prefsSpec, kMySignature, kMyPrefsFileType, 0);
  660.             if (ResError())
  661.                 return(nil);                                /* bail */
  662.             prefsID = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  663.             error = ResError();
  664.             if (error)
  665.                 return(nil);
  666.             
  667.         }
  668.     }
  669.     ReleaseResource(prefsNameStr);
  670.     return(prefsID);
  671. }
  672.  
  673. /* allows you to save the contents of the AEStatus window to disk.  Can be handy */
  674. void SaveAES(windowCHandle theWind, WindowPtr theWindPtr)
  675. {
  676. #pragma unused (theWindPtr)
  677. OSErr myErr;
  678. Str255 savePrompt;
  679. Str63 defaultName;
  680. StandardFileReply saveReply;
  681. FSSpec saveFileSpec;
  682. Handle theText;
  683. long toWrite;
  684. long textSize = 0;
  685. long currentOffset = 0;
  686. char carrageRet = 0x0d;
  687. long oneByte = 1;
  688. short fileRef;
  689. Boolean myWasChanged;
  690.     if (GetHandleSize((Handle)(*theWind)->fileAliasHandle) == 0) {
  691.         
  692.         GetIndString(savePrompt, kGeneralStrings, kAESSavePrompt);
  693.         GetIndString(defaultName,kGeneralStrings,kAESDefaultName);
  694.         StandardPutFile(savePrompt, defaultName, &saveReply);
  695.         if (!saveReply.sfGood)
  696.             return;
  697.         saveFileSpec = saveReply.sfFile;
  698.         if (saveReply.sfReplacing)
  699.             FSpDelete(&saveFileSpec);
  700.  
  701.  
  702.  
  703.     } else {
  704.         /* Resolve the old alias that was kept with the window  */
  705.         /* in this case I don't care if the alias needed to be updated or not, this ain't */
  706.         /* a real time critical routine */
  707.         myErr = ResolveAlias(nil, ((*theWind)->fileAliasHandle), &saveFileSpec, &myWasChanged);
  708.         if (myErr) {
  709.             ShowMe("\pResolving Alias ", myErr, __LINE__);
  710.             return;
  711.         }
  712.         /* kill current file, ignoring errors */
  713.         FSpDelete(&saveFileSpec);
  714.     }
  715.     SpinCursor();
  716.     /* I'm saving this as MPW TEXT */
  717.     myErr = FSpCreate(&saveFileSpec, kMPWSignature, 'TEXT', 1);
  718.     if (myErr) {
  719.         ShowMe("\pCreating AES file, Do you have it open in MPW? ", myErr, __LINE__);
  720.         InitCursor();
  721.         return;
  722.     }
  723.     
  724.     /* replace the nil handle with the alias record please, in our window data struct */
  725.     DisposHandle((Handle)(*theWind)->fileAliasHandle);
  726.     if (myErr = NewAlias(nil, &saveFileSpec, &((*theWind)->fileAliasHandle))) {
  727.         ShowMe("\pDuring New Alias ", myErr, __LINE__);
  728.         InitCursor();
  729.         return;
  730.     }
  731.     myErr = FSpOpenDF(&saveFileSpec, fsRdWrPerm, &fileRef);
  732.     if (myErr) {
  733.         ShowMe("\pOpening AES file  Do you have it open in MPW?", myErr, __LINE__);
  734.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  735.         return;
  736.     }
  737.     theText = (Handle)TEGetText((*theWind)->boxHandle);
  738.     textSize = GetHandleSize(theText);
  739.     HLock(theText);
  740. /* going to write 80 chars, carrage return, 80 chars, etc. */
  741.     do{
  742.     if(textSize > 80)
  743.         toWrite = 80;
  744.     else 
  745.         toWrite = textSize;
  746.         
  747.     myErr = FSWrite(fileRef, &toWrite, (Ptr)(*theText + currentOffset));
  748.     if(myErr){
  749.             ShowMe("\pWriting to AES file ", myErr, __LINE__);
  750.             break;
  751.     }
  752.     if(textSize < 80){
  753.     break;
  754.     } else {
  755.     SpinCursor();
  756.     FSWrite(fileRef, &oneByte, (Ptr)&carrageRet);
  757.     textSize -= 80;
  758.     currentOffset +=80;
  759.     }
  760.     }while(true);
  761.     HUnlock(theText);
  762.     FSClose(fileRef);
  763. /* make sure it gets updated now. */
  764. FlushVol("", saveFileSpec.vRefNum);    
  765. InitCursor();
  766.  
  767. }
  768.  
  769. OSErr KillOldPrefs(void)
  770. {
  771.     Handle prefsNameStr;
  772.     FSSpec prefsSpec;
  773.     short foundVREF;
  774.     OSErr error;
  775.     long foundDIR;
  776.     FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &foundVREF, &foundDIR);
  777.     prefsNameStr = GetResource('STR ', kPrefsFileString);
  778.     HLock(prefsNameStr); 
  779.     FSMakeFSSpec(foundVREF, foundDIR, (Str255)*prefsNameStr, &prefsSpec);
  780.     error = FSpDelete(&prefsSpec);
  781.     HUnlock(prefsNameStr);
  782.     ReleaseResource(prefsNameStr);
  783. return(error);
  784.  
  785. }
  786. #undef __FILES__
  787.